package com.hupu.jrs.components.jockeyjs

import java.util.*

/**
 * Composes a group of JockeyHandlers into a single structure, <br></br>
 * When perform is invoked on this handler it will invoke it on all of the handlers.<br></br>
 * They will be invoked in FIFO order, however if any are asynchronous, no guarantees can be made
 * for
 * execution order.
 *
 *
 * To maintain a single callback invariant, this handler will accumulate <br></br>
 * all the "complete" calls from the internal handlers.
 * <br></br><br></br>
 * Once all of the handlers have been called it this handler will signal completion.
 *
 * @author Paul
 */
open class CompositeJockeyHandler(vararg handlers: JockeyHandler) : JockeyHandler() {

    private var _listener: JockeyHandler.OnCompletedListener? = null

    private val _handlers = ArrayList<JockeyHandler>()

    private var _accumulator: JockeyHandler.OnCompletedListener? = null

    /**
     * Accumulates all the "completed" calls from the contained Handlers
     * Once all the handlers have completed this will signal completion
     *
     * @author Paul
     */
    private inner class AccumulatingListener () : JockeyHandler.OnCompletedListener {

        private val _size: Int
        private var _accumulated: Int = 0

        init {
            this._size = _handlers.size
            this._accumulated = 0
        }

        override fun onCompleted() {
            ++_accumulated

            if (_accumulated >= _size) completed(_listener)
        }
    }

    init {
        add(*handlers)
    }

    fun add(vararg handler: JockeyHandler) {
        _handlers.addAll(Arrays.asList(*handler))
    }

    fun clear(handler: JockeyHandler) {
        _handlers.clear()
    }

    override fun perform(payload: Map<Any, Any>, listener: JockeyHandler.OnCompletedListener) {
        this._listener = listener
        this._accumulator = AccumulatingListener()
        doPerform(payload)
    }

    override fun doPerform(payload: Map<Any, Any>) {
        for (handler in _handlers)
            handler.perform(payload, this._accumulator!!)
    }

    companion object {

        fun compose(vararg handlers: JockeyHandler): JockeyHandler {
            return CompositeJockeyHandler(*handlers)
        }
    }
}
